package com.itx.gatewayx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itx.gatewayx.domain.User;
import com.itx.gatewayx.mapper.UserMapper;
import com.itx.gatewayx.service.UserService;
import com.itx.gatewayx.utils.JwtUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * 用户服务实现类
 *
 * @author itx
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    
    private final UserMapper userMapper;
    private final JwtUtils jwtUtils;
    
    /**
     * 使用MD5加密密码
     * 
     * @param password 原始密码
     * @return 加密后的密码
     */
    private String encodePassword(String password) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hashInBytes = md.digest(password.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(hashInBytes);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("密码加密失败", e);
        }
    }
    
    /**
     * 校验密码
     * 
     * @param rawPassword 原始密码
     * @param encodedPassword 加密后的密码
     * @return 是否匹配
     */
    private boolean matchPassword(String rawPassword, String encodedPassword) {
        return encodePassword(rawPassword).equals(encodedPassword);
    }
    
    @Override
    public boolean checkUsernameExists(String username) {
        Long count = this.lambdaQuery()
                .eq(User::getUsername, username)
                .count();
        return count > 0;
    }
    
    @Override
    public boolean checkEmailExists(String email) {
        Long count = this.lambdaQuery()
                .eq(User::getEmail, email)
                .count();
        return count > 0;
    }
    
    @Override
    public Map<String, Object> login(String username, String password) {
        // 查询用户
        User user = this.lambdaQuery()
                .eq(User::getUsername, username)
                .eq(User::getDelFlag, 0)
                .one();
        
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 校验密码
        if (!matchPassword(password, user.getPassword())) {
            throw new RuntimeException("密码错误");
        }
        
        // 校验状态
        if (user.getStatus() != 1) {
            throw new RuntimeException("账号已被禁用");
        }
        
        // 生成token
        String token = jwtUtils.generateToken(user.getId(), user.getUsername());
        String refreshToken = jwtUtils.generateRefreshToken(user.getId(), user.getUsername());
        
        // 构建结果
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("refreshToken", refreshToken);
        
        // 移除敏感信息
        user.setPassword(null);
        result.put("user", user);
        
        return result;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(User user) {
        // 判断用户名是否已存在
        Long count = this.lambdaQuery()
                .eq(User::getUsername, user.getUsername())
                .count();
        
        if (count > 0) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 检查必要字段
        if (user.getUsername() == null || user.getUsername().trim().isEmpty()) {
            throw new RuntimeException("用户名不能为空");
        }
        
        if (user.getPassword() == null || user.getPassword().trim().isEmpty()) {
            throw new RuntimeException("密码不能为空");
        }
        
        if (user.getEmail() == null || user.getEmail().trim().isEmpty()) {
            throw new RuntimeException("邮箱不能为空");
        }
        
        // 加密密码
        user.setPassword(encodePassword(user.getPassword()));
        
        // 设置默认值
        user.setStatus(1);
        user.setRole("user");
        user.setIsPublisher(false);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        user.setDelFlag(0);
        
        // 保存用户
        return this.save(user);
    }
    
    @Override
    public Map<String, Object> refreshToken(String refreshToken) {
        // 验证token
        if (!jwtUtils.validateToken(refreshToken)) {
            throw new RuntimeException("刷新令牌已过期");
        }
        
        // 获取用户ID
        Long userId = jwtUtils.getUserIdFromToken(refreshToken);
        
        // 查询用户
        User user = this.getById(userId);
        if (user == null || user.getDelFlag() == 1) {
            throw new RuntimeException("用户不存在");
        }
        
        // 校验状态
        if (user.getStatus() != 1) {
            throw new RuntimeException("账号已被禁用");
        }
        
        // 生成新token
        String token = jwtUtils.generateToken(user.getId(), user.getUsername());
        String newRefreshToken = jwtUtils.generateRefreshToken(user.getId(), user.getUsername());
        
        // 构建结果
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("refreshToken", newRefreshToken);
        
        return result;
    }
    
    @Override
    public User getUserInfo(Long userId) {
        User user = this.getById(userId);
        if (user != null) {
            // 移除敏感信息
            user.setPassword(null);
        }
        return user;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserInfo(User user) {
        // 设置更新时间
        user.setUpdateTime(new Date());
        
        // 不允许更新密码和敏感字段
        user.setPassword(null);
        user.setUsername(null);
        user.setStatus(null);
        user.setRole(null);
        user.setDelFlag(null);
        
        return this.updateById(user);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean changePassword(Long userId, String oldPassword, String newPassword) {
        // 查询用户
        User user = this.getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 校验旧密码
        if (!matchPassword(oldPassword, user.getPassword())) {
            throw new RuntimeException("原密码错误");
        }
        
        // 更新密码
        User updateUser = new User();
        updateUser.setId(userId);
        updateUser.setPassword(encodePassword(newPassword));
        updateUser.setUpdateTime(new Date());
        
        return this.updateById(updateUser);
    }
    
    @Override
    public Page<User> getUserList(Long current, Long size, String username, String role) {
        Page<User> page = new Page<>(current, size);
        
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
                .eq(User::getDelFlag, 0)
                .like(StringUtils.hasText(username), User::getUsername, username)
                .eq(StringUtils.hasText(role), User::getRole, role)
                .orderByDesc(User::getCreateTime);
        
        Page<User> userPage = this.page(page, queryWrapper);
        
        // 移除敏感信息
        userPage.getRecords().forEach(user -> user.setPassword(null));
        
        return userPage;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserStatus(Long userId, Integer status) {
        if (status != 0 && status != 1) {
            throw new RuntimeException("状态值无效");
        }
        
        return userMapper.updateStatus(userId, status) > 0;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setPublisher(Long userId, Boolean isPublisher) {
        return userMapper.updatePublisherStatus(userId, isPublisher) > 0;
    }
    
    @Override
    public List<User> getUsersByRole(String role) {
        List<User> users = userMapper.selectByRole(role);
        
        // 移除敏感信息
        users.forEach(user -> user.setPassword(null));
        
        return users;
    }
} 